/***************************************************
 ** @Desc : This file for 代付
 ** @Time : 2019.04.10 15:51
 ** @Author : Joker
 ** @File : pay
 ** @Last Modified by : Joker
 ** @Last Modified time: 2019.04.10 15:51
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"recharge/models"
	"recharge/sys"
	"recharge/utils"
	"recharge/utils/interface_config"
	"strings"
)

type PayV2 struct {
	KeepSession
}

// 商户代付
// @router /merchant/do_pay_v2/?:params [post]
func (the *PayV2) DoRecharge() {
	userId := the.GetSession("userId").(int)

	//channel := the.GetString("channel")
	//merchant := the.GetString("merchant")
	accountNo := strings.TrimSpace(the.GetString("accountNo"))
	accountName := strings.TrimSpace(the.GetString("accountName"))
	mobileNo := strings.TrimSpace(the.GetString("mobileNo")) //验证码
	userType := the.GetString("userType")
	issuer := strings.TrimSpace(the.GetString("issuer"))
	accountType := the.GetString("accountType")
	bankNo := strings.TrimSpace(the.GetString("bankNo"))
	branchProvince := strings.TrimSpace(the.GetString("branchProvince"))
	branchCity := strings.TrimSpace(the.GetString("branchCity"))
	branchName := strings.TrimSpace(the.GetString("branchName"))
	money := strings.TrimSpace(the.GetString("money"))

	//获取客户端ip
	ip := the.Ctx.Input.IP()

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	msg, verify := payImpl.VerificationPayInfo(accountNo, accountName, money)
	if verify {

		//手机验证码或ip白名单判断
		code := the.GetSession("do_pay_code")
		msg, verify = payImpl.VerificationSmgOrIP(userId, code, ip, mobileNo)
		cookie := the.Ctx.GetCookie("do_pay_sms_cookie") //两分钟失效
		if cookie == "" {
			the.SetSession("do_pay_code", "")
			the.SetSession("do_pay_sms_cookie", "")
		}

		if verify {

			XFMerchant := merchantFactor.QueryOneMerchantForPay(money)
			if XFMerchant.MerchantNo == "" || XFMerchant.Id == 0 {
				msg = "请联系管理员更新代付通道"
			} else {

				record := models.WithdrawRecord{}
				record.UserId = userId
				record.MerchantNo = XFMerchant.MerchantNo

				record.SerialNumber = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(10)
				record.WhOrderId = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(8)

				yuanToFloat, _ := globalMethod.MoneyYuanToFloat(money)
				record.WhAmount = yuanToFloat
				record.WhUserType = userType
				record.WhAccountNo = accountNo
				record.WhAccountName = accountName

				if strings.Compare("2", userType) == 0 {
					accountType = "4"
				}
				record.WhAccountType = accountType

				record.WhBankNo = bankNo
				record.WhIssuer = issuer

				record.WhBranchProvince = branchProvince
				record.WhBranchCity = branchCity
				record.WhBranchName = branchName

				record.NoticeUrl = interface_config.XF_PAY_NOTICE_URL_V2 + record.WhOrderId

				nowTime := globalMethod.GetNowTime()
				record.CreateTime = nowTime
				record.EditTime = nowTime

				//状态以异步回调为准
				record.Status = utils.I

				// 多通道代付
				switch XFMerchant.ChannelType {
				case utils.XF:
					//先锋
					record.RecordType = utils.XF
					//判断可用余额,冻结提现金额
					enough, rMsg := userMdl.SelectOneUserUsableAmount(userId, yuanToFloat, record)
					if !enough {
						msg = rMsg
					} else {

						encode := encrypt.EncodeMd5([]byte(globalMethod.RandomString(32)))
						result, err := xfPayV2(record, encode, XFMerchant.SecretKey)
						if err != nil {
							msg = err.Error()
						} else {

							resp := models.XFPayResponseBody{}
							err = json.Unmarshal(result, &resp)
							if err != nil {
								sys.LogError("orderId=", record.WhOrderId, ", response data format is error: ", err)
								msg = "先锋代付响应数据格式错误"
							} else {

								if strings.Compare("00000", resp.ResCode) == 0 ||
									strings.Compare("00001", resp.ResCode) == 0 ||
									strings.Compare("00002", resp.ResCode) == 0 {
									flag = utils.SUCCESS_FLAG
								} else {
									sys.LogDebug("先锋代付错误：", resp)
									msg = "先锋代付错误：" + resp.ResMessage
								}
							}
						}
					}
				}
			}
		}
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 先锋代付
func xfPayV2(record models.WithdrawRecord, b, key string) ([]byte, error) {
	// 请求参数
	reqParams := url.Values{}
	reqParams.Add("version", interface_config.VERSION_V2)
	reqParams.Add("service", "REQ_WITHDRAW")
	reqParams.Add("merchantId", record.MerchantNo)

	blockKey, err := merchantImpl.XFHandleBlockKey(b, key)
	if err != nil {
		s := "先锋代付aes秘钥加密失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("tm", blockKey)

	// 需要的加密参数
	dataParams := models.XFPayData{}
	dataParams.MerchantNo = record.WhOrderId
	dataParams.Source = "1"
	fen, _ := globalMethod.MoneyYuanToFen(record.WhAmount)
	dataParams.Amount = fen
	dataParams.TransCur = "156"
	dataParams.UserType = record.WhUserType
	dataParams.AccountNo = record.WhAccountNo
	dataParams.AccountName = record.WhAccountName
	dataParams.MobileNo = record.WhMobileNo
	dataParams.BankNo = record.WhBankNo

	terminalParams := models.TerminalParams{}
	terminalParams.MerEquipmentIp = globalMethod.RandIpAddr()
	ter, _ := json.Marshal(&terminalParams)
	dataParams.TerminalParams = string(ter)

	if strings.Compare("2", record.WhUserType) == 0 {
		dataParams.Issuer = record.WhIssuer
	}

	dataParams.BranchProvince = record.WhBranchProvince
	dataParams.BranchCity = record.WhBranchCity
	dataParams.BranchProvince = record.WhBranchName

	dataParams.NoticeUrl = record.NoticeUrl

	// 加密参数
	dataString, _ := json.Marshal(&dataParams)
	data, err := AES.AesEncryptV2(string(dataString), b)
	if err != nil {
		return nil, err
	}
	reqParams.Add("data", data)

	// 生成签名
	respParams := map[string]string{}
	respParams["service"] = "REQ_WITHDRAW"
	respParams["version"] = interface_config.VERSION_V2
	respParams["merchantId"] = record.MerchantNo
	respParams["tm"] = blockKey
	respParams["data"] = data
	params := globalMethod.ToStringByMap(respParams)

	signBytes, err := merchantImpl.XFGenerateSignV2(params, interface_config.PRIVATE_KEY)
	if err != nil {
		s := "先锋代付生成签名失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("sign", string(signBytes))

	// 发送请求
	resp, err := http.PostForm(interface_config.XF_RECHANGE_URL, reqParams)
	if err != nil {
		s := "先锋代付请求失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	// 处理响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		s := "先锋代付响应为空"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	defer resp.Body.Close()

	respData := models.RespData{}
	err = json.Unmarshal(body, &respData)
	if err != nil {
		s := "先锋代付响应数据格式错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	if respData.Data == "" {
		sys.LogInfo("先锋代付响应：", string(body))
		return nil, errors.New("先锋代付响应data为空！")
	}

	s, err := merchantImpl.DecryptRespDataByPrivateKey(respData.Tm)
	bytes, err := AES.AesDecryptV2([]byte(respData.Data), s)
	if err != nil {
		s := "先锋代付响应解密错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	return bytes, err
}
